package com.mlh.myspring.component;

import com.mlh.myspring.annotation.Component;
import com.mlh.myspring.processor.BeanPostProcessor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Component
//MlhBeanPostProcessor Bean后置处理器本身也是一个 bean
public class MlhBeanPostProcessor implements BeanPostProcessor {
    @Override
    //该方法时在 bean 创建好后，进行初始化前调用
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        //这里程序员来决定业务逻辑，spring 只是提供处理机制
        System.out.println("后置处理器MlhBeanPostProcessor before被调用  bean类型="+bean.getClass()+"beanName="+beanName);
        return bean;
    }

    @Override
    //该方法时在 bean 创建好后，初始化完成后调用
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        //这里程序员来决定业务逻辑，spring 只是提供处理机制
        System.out.println("后置处理器MlhBeanPostProcessor after被调用  bean类型="+bean.getClass()+"beanName="+beanName);

        //实现AOP 返回代理对象 即对Bean进行包装
        //为了简单 这边仅对指定的Phone进行一个代理
        //原生spring 则通过切面类的注解来实现功能
        //这里使用的硬编码，不灵活, 但是已经把 AOP 核心机制说清楚了 要写的更加详细的话和AOP机制就没多大关系了 因此没有必要继续下去了
        if("phone".equals(beanName)){
            Object proxyInstance = Proxy.newProxyInstance(MlhBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("method=" + method.getName());
                    Object result = null;
                    if ("work".equals(method.getName())) {//检测切入点
                        SmartAnimalAspect.showBeginLog();//切面类方法
                        result = method.invoke(bean, args);
                        SmartAnimalAspect.showSuccessLog();//切面类方法
                    } else {
                        result = method.invoke(bean, args);
                    }
                    return result;
                }
            });
            //如果bean是需要返回代理对象，这里则直接返回创建好的代理对象
            return proxyInstance;
        }
        //如果不需要AOP 则返回原生的bean
        return bean;
    }
}
